package com.googlecode.yoohoo.xep.register;

import java.util.Dictionary;
import java.util.Hashtable;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceRegistration;

import com.googlecode.yoohoo.config.IConfigManager;
import com.googlecode.yoohoo.io.socket.stream.NegotiationPhase;
import com.googlecode.yoohoo.io.socket.stream.StreamFeatureContribution;
import com.googlecode.yoohoo.osgi.AbstractBundleActivator;
import com.googlecode.yoohoo.utils.AppUtils;
import com.googlecode.yoohoo.utils.Constants;
import com.googlecode.yoohoo.utils.OsgiUtils;
import com.googlecode.yoohoo.xep.data.protocol.Data;
import com.googlecode.yoohoo.xep.data.protocol.DataParserFactory;
import com.googlecode.yoohoo.xep.register.feature.Register;
import com.googlecode.yoohoo.xep.register.protocol.RegisterParserFactory;
import com.googlecode.yoohoo.xmppcore.parsing.ParserContribution;
import com.googlecode.yoohoo.xmppcore.protocol.parsing.ProtocolRelation;
import com.googlecode.yoohoo.xmppcore.protocol.stanza.Iq;
import com.googlecode.yoohoo.xmppcore.stanza.IStanzaHandler;
import com.googlecode.yoohoo.xmppcore.stanza.IStanzaHandlerFactory;
import com.googlecode.yoohoo.xmppcore.stream.INegotiationContext;

public class Activator extends AbstractBundleActivator {
	private static final String BUNDLE_IO_SOCKET_SYMBLIC_NAME = "com.googlecode.yoohoo.io.socket";
	private ServiceRegistration handlerFactoryRegistration;
	private ServiceRegistration featureRegistration;
	private ServiceRegistration dataParserRegistration;
	private ServiceRegistration registerParserRegistration;
	
	@Override
	public void doStart(BundleContext context) throws Exception {
		activateIoSocketBundle(context);
		boolean tlsRequired = getTlsRequired(context);
		registerParsers(context);
		registerStanzaHandler(context, tlsRequired);
		registerStreamFeature(context, tlsRequired);
	}

	private void registerStanzaHandler(BundleContext context,
			boolean tlsRequired) {
		Dictionary<Object, Object> properties = new Hashtable<Object, Object>();
		if (tlsRequired) {
			properties.put(IStanzaHandler.KEY_STANZA_HANDLER_TYPE, NegotiationPhase.AFTER_TLS.toString());
		} else {
			properties.put(IStanzaHandler.KEY_STANZA_HANDLER_TYPE, NegotiationPhase.AFTER_INITIAL_STREAM.toString());
		}
		
		handlerFactoryRegistration = context.registerService(IStanzaHandlerFactory.class.getName(),
				new RegisterHandlerFactory<INegotiationContext>(context), properties);
	}

	private void registerParsers(BundleContext context) {
		ParserContribution dataParserContribution = new ParserContribution(new DataParserFactory(),
			new ProtocolRelation(com.googlecode.yoohoo.xep.register.protocol.Register.PROTOCOL_KEY,
					Data.PROTOCOL_KEY));
		Dictionary<Object, Object> properties = new Hashtable<Object, Object>();
		properties.put(Constants.KEY_SERVICE_INSTANCE_NAME, Constants.CONSTANT_XMPP_STREAM);
		dataParserRegistration = context.registerService(ParserContribution.class.getName(),
				dataParserContribution, properties);
		
		ParserContribution registerParserContribution = new ParserContribution(new RegisterParserFactory(),
			new ProtocolRelation(Iq.PROTOCOL_KEY, com.googlecode.yoohoo.xep.register.protocol.Register.PROTOCOL_KEY));		
		properties = new Hashtable<Object, Object>();
		properties.put(Constants.KEY_SERVICE_INSTANCE_NAME, Constants.CONSTANT_XMPP_STREAM);
		registerParserRegistration = context.registerService(ParserContribution.class.getName(),
				registerParserContribution, properties);
	}

	private void registerStreamFeature(BundleContext context, boolean tlsRequired) {
		StreamFeatureContribution featureContribution;
		if (tlsRequired) {
			featureContribution = new StreamFeatureContribution(new Register(), NegotiationPhase.TLS);
			
		} else {
			featureContribution = new StreamFeatureContribution(new Register(), NegotiationPhase.INITIAL_STREAM);
		}
		
		featureRegistration = context.registerService(StreamFeatureContribution.class.getName(),
				featureContribution, null);
	}

	private void activateIoSocketBundle(BundleContext context)
			throws BundleException {
		Bundle ioSocketBundle = OsgiUtils.getBundle(context, BUNDLE_IO_SOCKET_SYMBLIC_NAME);
		if (Bundle.ACTIVE != ioSocketBundle.getState()) {
			ioSocketBundle.start();
		}
	}

	private boolean getTlsRequired(BundleContext context) {
		IConfigManager configManager = AppUtils.getConfigManager(context, BUNDLE_IO_SOCKET_SYMBLIC_NAME);
		if (configManager != null)
			return configManager.getBoolean("tls.required");
		
		return true;
	}

	@Override
	public void doStop(BundleContext context) throws Exception {
		if (featureRegistration != null)
			featureRegistration.unregister();
		
		if (handlerFactoryRegistration != null)
			handlerFactoryRegistration.unregister();
		
		if (registerParserRegistration != null) {
			registerParserRegistration.unregister();
		}
		
		if (dataParserRegistration != null) {
			dataParserRegistration.unregister();
		}
	}
}
